package com.codefish.framework.spring.beans.annotation;

import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author <a href='https://gitee.com/hzf2281'>codefish</a>
 * @version 1.0.0
 * @since 2022/11/06 下午 04:25
 */
public class InjectMetadata {

    List<InjectElement> injectElements = new ArrayList<>();

    public void inject(Object target, String beanName) {
        for (InjectElement injectElement : injectElements) {
            try {
                injectElement.inject(target, beanName);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }

    public void addInjectElement(InjectElement injectElement) {
        injectElements.add(injectElement);
    }


    public static abstract class InjectElement {
        Member member;
        boolean isField = false;


        protected InjectElement(Member member) {
            this.member = member;
            if (member instanceof Field) {
                this.isField = true;
            }
        }

        public void inject(Object target, String requestingBeanName) throws Throwable {
            //获取资源对象
            Object resource = getResourceToInject(target, requestingBeanName);
            //注入资源对象到target
            if (this.isField) {
                if (resource != null) {
                    Field field = (Field) member;
                    field.setAccessible(true);
                    field.set(target, resource);
                }
            } else {
                //method
                Method method = (Method) member;
                method.setAccessible(true);
                method.invoke(target, resource);
            }
        }

        /**
         * 返回依赖的资源对象，由子类实现
         *
         * @param target             目标对象
         * @param requestingBeanName 目标对象的beanName
         * @return 目标对象依赖的资源对象
         */
        public Object getResourceToInject(Object target, String requestingBeanName) {
            return null;
        }
    }

}
